package ru.tpu.osu.faces.beans;

import java.io.Serializable;
import java.sql.BatchUpdateException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.*;
import javax.faces.context.FacesContext;

import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.exception.ConstraintViolationException;

import ru.tpu.osu.faces.dao.*;

@ManagedBean(name="dialogueBean")
@RequestScoped
public class DialogueBean extends BaseBean implements Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 2334648517659556829L;
	private User user;
	private String login;
	private List<PrivateMessage> messages;
	private List<PrivateMessage> lastMessages;
	private PrivateMessage newMessage = new PrivateMessage();
	private Integer countUnreadMessages;
	  
	public List<PrivateMessage> getLastMessages() {
		if (lastMessages == null && auth.getLoggedIn()){
			List<PrivateMessage> allMessages = new ArrayList<PrivateMessage>();
			allMessages.addAll(auth.getCurrentUser().getSentMessages());
			allMessages.addAll(auth.getCurrentUser().getRecievedMessages());
			HashMap<User, PrivateMessage> uniqueMessages = new HashMap<User, PrivateMessage>(); 
			for (PrivateMessage privateMessage : allMessages) {
				if (!privateMessage.getSender().equals(auth.getCurrentUser()) && !uniqueMessages.containsKey(privateMessage.getSender()) ){
					uniqueMessages.put(privateMessage.getSender(), privateMessage);
				}else if (!privateMessage.getReciever().equals(auth.getCurrentUser()) && !uniqueMessages.containsKey(privateMessage.getReciever()) ){
					uniqueMessages.put(privateMessage.getReciever(), privateMessage);
				}
				privateMessage.setFirstParty(auth.getCurrentUser());
			}
			lastMessages = new ArrayList<PrivateMessage>(uniqueMessages.values());
			if (lastMessages!= null){
				Collections.sort(lastMessages);
				Collections.reverse(lastMessages);
			}
			
		}
		return lastMessages;
	}

	public Integer getCountUnreadMessages() {
		if (countUnreadMessages == null && auth.getLoggedIn()) {
			countUnreadMessages = HibernateUtil.getSession().createCriteria(PrivateMessage.class)
		    .add(Restrictions.eq("isRead", false) )
		    .add(Restrictions.eq("reciever", auth.getCurrentUser()) )
		    .list().size();
		}
		return countUnreadMessages;
	}

	public PrivateMessage getNewMessage() {
		return newMessage;
	}

	public void setNewMessage(PrivateMessage newMessage) {
		this.newMessage = newMessage;
	}

	public List<PrivateMessage> getMessages() {
		if (messages == null && getUser()!=null && auth.getLoggedIn() ){
			messages = HibernateUtil.getSession().createCriteria(PrivateMessage.class)
			.add( Restrictions.or(Restrictions.and(Restrictions.eq("sender", auth.getCurrentUser()), Restrictions.eq("reciever", getUser())),
									Restrictions.and(Restrictions.eq("reciever", auth.getCurrentUser()),Restrictions.eq("sender", getUser()))))
			.addOrder( Order.desc("sentDate") )
		    .list();
				HibernateUtil.getSession().beginTransaction();
				
				for (PrivateMessage privateMessage : messages) {
					if (privateMessage.getReciever().equals(auth.getCurrentUser()) && (privateMessage.getIsRead() == null || !privateMessage.getIsRead())){
						privateMessage.setIsRead(true);
						HibernateUtil.getSession().saveOrUpdate(privateMessage);
					}
				}
				try {
					HibernateUtil.getSession().getTransaction().commit();
				}
				catch (Exception e)
				{
					HibernateUtil.getSession().getTransaction().rollback();
				}
		}
		return messages;
	}

	public void setMessages(List<PrivateMessage> messages) {
		this.messages = messages;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public String getLogin() {
		return login;
	}

	public void setLogin(String login) {
		if (login != null) {
			user = (User) HibernateUtil.getSession().get(User.class, login);
			if (user != null){
				HibernateUtil.getSession().refresh(user);
			}
		}
	
		this.login = login;
	}
	
	public String sendMessage() {
		if (getUser()!=null && auth.getLoggedIn() && !getUser().equals(auth.getCurrentUser()) ){
			getNewMessage().setReciever(getUser());
			getNewMessage().setSender(auth.getCurrentUser());
			getNewMessage().setSentDate(new Date());
			HibernateUtil.getSession().beginTransaction();
			
			HibernateUtil.getSession().saveOrUpdate(getNewMessage());
			try {
				HibernateUtil.getSession().getTransaction().commit();
				messages = null;
				return "dialogue?faces-redirect=true&amp;includeViewParams=true";
			}
			catch (ConstraintViolationException e)
			{
				String message = new String(e.getMessage());
				BatchUpdateException bu = (BatchUpdateException) e.getCause();
				if (bu != null)
				{
					message = bu.getNextException().getMessage();
				}
				FacesMessage fm = new FacesMessage(message);
				FacesContext.getCurrentInstance().addMessage("publicMessages", fm);
				HibernateUtil.getSession().getTransaction().rollback();
			}
		}
		return "dialogue?includeViewParams=true";
	}
}

